// 数据库
export default class DB {
  private readonly dbName: string // 数据库名称
  private db: any // 数据库对象

  constructor(dbName: string) {
    this.dbName = dbName;
  }

  // 打开数据库
  public openStore(stores: any) {
    // 检查是否在浏览器环境中
    if (typeof window === "undefined") {
      console.warn("IndexedDB 只能在浏览器环境中使用");
      return Promise.resolve(false); // 返回一个 resolved 的 Promise，避免后续操作报错
    }

    const request = window.indexedDB.open(this.dbName, 2);
    return new Promise((resolve, reject) => {
      // 数据库成功打开时的回调
      request.onsuccess = (event: any) => {
        this.db = event.target.result;
        resolve(true);
      };
      // 数据库打开时失败的回调
      request.onerror = (event: any) => {
        console.log("数据库打开失败", event);
        reject(event);
      };
      // 数据升级时的回调 在第一次打开数据库时 会首先打开这个事件
      request.onupgradeneeded = (event: any) => {
        // 数据库升级成功
        const { result }: any = event.target;
        // 初始化多个objectStore对象仓库
        for (const storeName in stores) {
          const { keyPath, indexs } = stores[storeName];
          if (!result.objectStoreNames.contains(storeName)) {
            /**
             * 没有表则新建表
             * keyPath: 主键，主键(key)是默认建立索引的属性
             * autoIncrement: 是否自增
             * createObjectStore 会返回一个对象仓库objectStore(即新建一个表)
             * */
            const store = result.createObjectStore(storeName, {
              autoIncrement: true,
              keyPath
            });
            if (indexs && indexs.length) {
              indexs.forEach((v: string) => {
                // createIndex可以新建索引, unique字段是否唯一
                store.createIndex(v, v, { unique: false });
              });
            }
            store.transaction.oncomplete = (e: any) => {
              console.log("创建对象仓库成功", e);
            };
          }
        }
      };
    });
  }

  // 新增/修改数据库数据
  updateItem(storeName: string, data: any) {
    // 写入到objectStore
    const store = this.db.transaction([storeName], "readwrite").objectStore(storeName);
    // 可以使用add(新增)和put(新增和修改)
    const request = store.put({
      ...data,
      updateTime: new Date().getTime()
    }); // 返回一个连接对象
    return new Promise((resolve, reject) => {
      request.onsuccess = (event: any) => {
        // console.log("数据写入成功", event);
        resolve(event.target.result);
      };
      request.onerror = (event: any) => {
        // console.log("数据写入失败", event);
        reject(event);
      };
    });
  }

  // 删除数据
  deleteItem(storeName: string, key: number | string) {
    // 写入到objectStore
    const store = this.db.transaction([storeName], "readwrite").objectStore(storeName);
    const request = store.delete(key);
    return new Promise((resolve, reject) => {
      request.onsuccess = (event: any) => {
        // console.log("数据删除成功", event);
        resolve(event);
      };
      request.onerror = (event: any) => {
        // console.log("数据删除失败", event);
        reject(event);
      };
    });
  }

  // 查询所有数据
  getList(storeName: string) {
    const store = this.db.transaction(storeName).objectStore(storeName);
    const request = store.getAll();
    return new Promise((resolve, reject) => {
      request.onsuccess = (event: any) => {
        // console.log("获取所有数据成功", event.target.result)
        resolve(event.target.result);
      };
      request.onerror = (event: any) => {
        // console.log("获取所有数据失败", event);
        reject(event);
      };
    });
  }

  // 查询某一条数据
  getItem(storeName: string, key: number | string) {
    const store = this.db.transaction(storeName).objectStore(storeName);
    const request = store.get(key);
    return new Promise((resolve, reject) => {
      request.onsuccess = (event: any) => {
        // console.log("成功查询到", event.target.result);
        resolve(event.target.result);
      };
      request.onerror = (event: any) => {
        reject(event);
        // console.log("获取某条数据失败", event);
      };
    });
  }
}
